Skip to content

add Sa token ehcache plugin #811

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from

Conversation

sanyang176
Copy link

add ehcache plugin for satoken. This pr lncludes plugin module and demo module.

@sanyang176 sanyang176 changed the title Sa token ehcache add Sa token ehcache plugin Jun 25, 2025
Copy link

@mengnankkkk mengnankkkk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

您好,我已对 PR #811 进行了代码审查,以下是一些发现和建议:

  1. 依赖版本管理: sa-token-demo/sa-token-demo-ehcache/pom.xmlsa-token.version 硬编码为 1.44.0,建议统一版本管理,例如在父 pom.xml 中定义 sa-token.version 并在所有子模块中引用,并与主项目的 Spring Boot 版本保持一致。

  2. Ehcache CacheManager 生命周期管理: 在 SaMapPackageForEhcache 中,CacheManager 是一个 static final 字段,通过 EhcacheConfig.CreateCacheManager() 初始化。这意味着 CacheManager 在应用程序启动时创建一次,并在整个应用程序生命周期中保持活动状态。虽然 EhcacheConfig 提供了 CloseCacheManager 方法,但在 SaMapPackageForEhcache 中并没有看到显式的关闭操作。这可能导致资源泄漏,尤其是在应用程序关闭时。建议在应用程序关闭时(例如通过 Spring 的 @PreDestroyDisposableBean 接口)显式关闭 CacheManager

  3. Ehcache 缓存配置: SaMapPackageForEhcacheCacheConfigurationBuilder 使用 ResourcePoolsBuilder.heap(Integer.MAX_VALUE)ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(Long.MAX_VALUE))。这意味着缓存将使用堆内存,并且永不过期。对于 Sa-Token 这种需要管理 Token 过期时间的场景,这显然是不合理的。SaTokenDaoEhcache 中的 setupdate 方法需要将 timeout 参数转换为 Ehcache 的过期策略。

  4. SaTokenDaoEhcache 实现: getTimeout 方法返回 -1,表示永不过期,这与 Sa-Token 的设计不符。setupdate 方法需要将 Sa-Token 的 timeout 参数转换为 Ehcache 的过期时间。get 方法中,如果 cache.get(key) 返回 null,应该返回 null,而不是 null 字符串。searchData 方法的实现是遍历所有 key,对于 Ehcache 来说,这可能不是最高效的查询方式,可以考虑优化。

  5. 代码规范和可读性: GlobalException.java 中的 e.printStackTrace() 在生产环境中不建议直接使用,应该使用日志框架记录异常。

  6. 测试: PR 中只包含了 demo 模块,没有看到 sa-token-ehcache 模块的单元测试或集成测试。对于一个新的插件模块,应该有充分的测试来验证其功能和稳定性,特别是 Ehcache 的缓存行为和过期时间管理。

但 Ehcache 缓存的过期时间管理是核心问题,需要确保 Sa-Token 的过期机制能够正确映射到 Ehcache 上,并且需要添加充分的测试。

@sanyang176
Copy link
Author

sanyang176 commented Jul 13, 2025

您好,非常感谢您对pr811的审查意见。对于这份意见,我有一些疑问和修改方案,还麻烦您看一下是否合理:

  1. 依赖版本管理的问题:这里跟其他的插件配置方式一样,父pom是springboot的标准pom配置,即spring-boot-starter-parent,而没有其他的父pom文件。如果增加父pom,那么原来的父pom就不能引入了,maven版本,springbootweb版本的依赖等都要引入。此外,由于其他插件都是这样hard code的,这样改页跟其他插件的代码风格完全不同,感觉不是很合适
  2. ehcache cachemanager生命周期管理问题:目前的生命周期是在组件被加载时调用createcachemanager,在组件被卸载时调用SaTokenDaoForEhcache中的destroy方法,是存在显式的关闭操作的,即目前ehcache的生命周期跟这个组件加载/卸载的时机是同步的。写的时候考虑过使用sproingboot@predestory等注解进行生命周期的管理,但这个插件设计的初衷是开发成一个通用型插件,详情可以看https://sa-token.cc/doc.html#/fun/plugin-dev?id=_1%e3%80%81%e6%8f%92%e4%bb%b6%e5%bc%80%e5%8f%91,所以使用springboot进行周期管理不是很合适,故而采用satokendao里面的destory方法进行周期管理。
  3. ehcache缓存配置: 这个我理解是否应该跟caffeine里面的配置类似,这里所谓的“永不过期”,只是默认值,具体的过期时间由timedcache中的expiredmap来管理,这一点可以参考caffeine的插件开发,此插件里面设置的默认值就是最大值。比如您说的ehcache什么时候过期,可以在satimedchache中看到,在set和update的时候,expiremap一直在更新,而在get的时候,通过clearKeyByTimeout进行了是否过期的判断。因此关于这一点,我理解ehcache和caffeine的管理方式是否应该是类似的,希望您能进一步说明
  4. satokenehcache的实现: 理由跟3类似,我仿照caffeine插件的处理方式进行开发的,如果这两者之间有比较大的区别,还希望您能给予指正。searchdata方法中遍历所有key的方法,我经过查询,使用stream api应该是最能使用大数据量和并行处理的,并且内存占用也比较低, 我还查到有使用getkeys和iterator方式的,不过通过查询资料性能都没有stream方式好,您更推荐什么方式呢。
  5. 代码规范和可读性: 可以考虑Lombok框架,但还是跟1一样的问题,其他的demo都是这么写的,并且我理解这只是一个demo,如果其他要使用我这个插件,他们应该自己写对应的webapplication。如果说我需要跟其他demo不一样,这样做的原因是什么呢,或者说其他demo为什么都用的printstacktrace。
  6. 测试:这个我在写的时候也考虑过,但是我看到所有的单元测试都在sa-token-test这个文件夹下,并且主要是针对sa-token-core里面的函数进行的,而对于所有的插件,我没有找到它们对应的单元测试的位置,如果确实需要写单元测试,那么应该写在什么位置呢?

以上是我的疑问和修改方案,最后还是非常感谢您,并希望您能进一步指教

@sanyang176 sanyang176 closed this Jul 13, 2025
@sanyang176 sanyang176 reopened this Jul 13, 2025
@mengnankkkk
Copy link

1.理解您的考虑,当前插件都采用 spring-boot-starter-parent 作为父 pom,确实统一风格很重要。如果后续插件数量增多或依赖管理变复杂,可以考虑通过 BOM 或 properties 方式在父 pom 统一管理版本,既不影响现有风格,也便于后期维护。
2.您的 destroy 方法确实实现了显式关闭,且插件设计为通用型,避免强依赖 Spring 生命周期是合理的。建议在文档或注释中明确 destroy 方法的调用时机,提醒用户在卸载或关闭组件时务必调用,避免资源泄漏。
3.您的理解没问题,和 caffeine 插件类似,实际过期时间由 expiredMap 管理。建议在文档中补充说明,明确 Ehcache 的默认配置和实际过期机制,方便用户理解和排查问题,这是我没有考虑周到的问题。
4.stream API 在大数据量下确实有优势。如果后续有性能瓶颈,可以考虑 benchmark 不同实现方式。该项目的确stream更有优势👍
5.demo 保持和其他示例一致没有问题
6.感觉可以新建插件独立的测试包

最后感谢您的回复,我考虑问题不周,多多包涵。再次感谢您的回复。

@sanyang176
Copy link
Author

在destory的注释中有提及显式关闭的时机。请问开发插件的pr 合并的规则是什么呢,除了demo文件,其他文件比如插件的文档和独立测试包也要包括在这个pr中么

@mengnankkkk
Copy link

mengnankkkk commented Jul 14, 2025

在destory的注释中有提及显式关闭的时机。请问开发插件的pr 合并的规则是什么呢,除了demo文件,其他文件比如插件的文档和独立测试包也要包括在这个pr中么

https://github.com/sa-tokens/sa-token-three-plugin 中有第三方插件的仓库,应该可以提交PR到这里面。或者直接提交到插件包下面吧。我也不太清楚。其他的文件应该也包含在此次PR中

@sanyang176
Copy link
Author

好的,我去研究一下这个网站,谢谢了~

@sanyang176
Copy link
Author

@sanyang176 sanyang176 closed this Jul 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants